<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * share_service.php
 *
 * @author  :  Skiychan <developer@zzzzy.com>
 * @created :  2015/4/14
 * @modified:  
 * @version :  0.0.1
 */
class Share_service extends MY_Service {

    public function __construct() {
        parent::__construct();
        $this->load->language('files');
        $this->load->model('share_model');
        $this->load->model('user_files_model');
    }

    public $last_share_id=0;

    /**
     * 添加分享信息
     * @param $share 链接信息
     * @param $slist 文件列表信息
     * @return bool
     */
    public function add($share, $slist) {

        if (empty($share) || empty($slist))
            return $this->set_error(1003);

        //添加分享
        $this->share_model->add_share($share);
        $flag = $this->db->affected_rows();
        if (empty($flag))
            return $this->set_error(1002);

        $this->last_share_id = $this->share_model->get_insert_id();
        $list_arr = array();
        foreach ($slist as $keys => $values) {
            $list_arr[$keys]['lid'] = $this->last_share_id;
            $list_arr[$keys]['type'] = $values['ctype'];
            $list_arr[$keys]['fid'] = $values['c_uuid'];
        }
        //添加列表到list表
        $this->share_model->insert_share_list($list_arr);

        return true;
    }

    /**
     * 添加分享信息
     * @param $share 链接信息
     * @param $files 文件id组
     * @param $folders 文件夹id组
     * @return bool
     */
    public function doadd($share, $files, $folders) {
        if (empty($share) ||
            (empty($files) && empty($folders))) {
            return $this->set_error(1003);
        }

        //初始化为数组
        if (empty($files))
            $files = array();
        if (empty($folders))
            $folders = array();

        //添加分享
        $this->share_model->add_share($share);
        $flag = $this->db->affected_rows();
        if (empty($flag))
            return $this->set_error(1002);

        $this->last_share_id = $this->share_model->get_insert_id();
        $data_arr = array();
        foreach ($files as $keys => $vid) {
            $data_arr[] = array(
                'lid' => $this->last_share_id,
                'type' => 1,
                'fid' => $vid
            );
        }
        foreach ($folders as $keys => $vid) {
            $data_arr[] = array(
                'lid' => $this->last_share_id,
                'type' => 2,
                'fid' => $vid
            );
        }

        //添加列表到list表
        $this->share_model->insert_share_list($data_arr);
        return true;
    }

    /**
     * 邮件分享
     * @param string $share_code    分享码
     * @param string $email_str     邮箱列表
     * @param string $name          分享列表名
     * @param string $password      分享密码
     * @param string $remark        备注
     * @param string $uemail        发送者邮箱
     * @return bool
     */
    public function send_email($share_code, $email_str, $name="", $password="", $remark="", $uemail="") {
        $this->load->language(array('sender'));
        $tpl = $this->lang->line("email_share_link_tpl");

        $footHtml ='';
        $friendHtml = '';
        $pwdHtml = '';

        if (empty($uemail)) {
            $subject = $tpl['subject']['other'];
        } else {
            $subject = sprintf($tpl['subject']['email'], $uemail);
            $friendHtml = sprintf($tpl['friend'], $uemail);
            $footHtml = $tpl['footer'];
        }

        $host = site_url();
        $url =  $host.'/s/'.$share_code;
        if (! empty($password))
            $pwdHtml = sprintf($tpl['password'], $password);

        $content = str_replace(
            array("[host]", "[url]", "[share_name]", "[remark]", "[pwdHtml]", "[footHtml]","[friendHtml]"),
            array($host, $url, $name, $remark, $pwdHtml, $footHtml, $friendHtml),
            $tpl['content']
        );

        $this->load->library('email');
        $sender = $this->config->item("share_email_from_account","user_common");
        $this->email->from($sender[0], $sender[1]);
        $this->email->reply_to($uemail, $uemail);
        $this->email->bcc($email_str);
        $this->email->subject($subject);
        $this->email->message($content);

        if(! $this->email->send())
            return $this->set_error(6001);

        return true;
    }

    /**
     * 取得一个文件/文件夹名
     * @param $id 文件的id
     * @param @type 文件类型
     * @return name
     */
    public function get_share_name($id, $type) {
        if (empty($id) || empty($type)) return $this->set_error(1003);

        $res = $this->share_model->get_share_name($id, $type);
        return $res['name'];
    }

    /**
     * 获取接收者的的信息
     * @param $uid 用户id
     * @param $type 类型 1邮件, 2短信
     * @return bool
     */
    public function get_share_receivers($uid, $type) {
        if (empty($uid) || empty($type))  return $this->set_error(1003);

        $where = array(
            'uid' => $uid,
            'type' => $type
        );
        return $this->share_model->get_share_receivers($where);
    }

    /**
     * 查询一组文件信息
     * @param $uid
     * @param $fids 文件列表id
     * @param string $where 查询条件
     * @return null
     */
    public function get_file_list($uid, $fids, $where='') {
        if (empty($uid) || empty($fids))
            return $this->set_error(1003);

        return $this->share_model->get_file_list($uid, $fids, $where);
    }

    /**
     * @param $uid uid
     * @param $fids 顶级文件夹列表
     * @param string $field 文件夹 查询字段
     * @param string $file_field 文件查询字段
     * @return array|bool
     */
    public function get_folder_files($uid, $fids, $field="id,name,path,access_denied,deleted", $file_field="id,name,folder_id,deleted,access_denied") {
        if (empty($uid) || empty($fids)) return $this->set_error(1003);

        $parent_path = '';  //当前下载的父级路径
        //当前查询的文件夹是否可访问且未删除
        $share_folders = $this->get_folders_info($uid, $fids, array('access_denied' => 0, 'deleted' => 0));
        if (! $share_folders) return $this->set_error(1004);
        if (empty($parent_path)) $parent_path = $share_folders[0]['path'];  //父级路径

        //所有的子目录及本身的信息
        $folder_children = $this->user_files_model->get_folder_children($uid,$fids,TRUE,$field);

        //拒绝访问/删除的目录
        $unpass_fds = array();
        foreach ($folder_children as $key => $fd) {
            if (($fd['access_denied'] == 1)|| ($fd['deleted'] == 1)) {
                $unpass_fds[] = $fd['id'];
            }
        }

        $new_children = array();  //提取之后整理的文件夹(父级目录也无权的)
        $pass_fds = array();  //可访问的子目录
        foreach ($folder_children as $keys => $child) {
            $cre_path1 =  $child['path'].",".$child['id'];
            //剃除父级路径,只取当前下载的路径新建文件夹
            $cre_path2 = str_replace($parent_path.",", "", $cre_path1);
            $cre_path = explode(",", $cre_path2);

            foreach ($cre_path as $key => $pt_id) {
                //此目录的父级包含在access_denied=1中
                if (in_array($pt_id, $unpass_fds)) {
                    $pass_fds['unpass'][] = $child['id'];
                    continue 2;  //跳过本次记录
                }
            }

            //重新组合子孙文件夹,剃除最顶层目录
            $child['path'] = $cre_path2;
            $new_children[] = $child;
            $pass_fds['pass'][] = $child['id'];
        }
        $descendant_files = $this->user_files_model->get_folder_files($uid, $fids, TRUE, $file_field);

        $result = array(
            'files' => $descendant_files,
            'fds' => $pass_fds,
            'folders' => $new_children
        );
        return $result;
    }

    /**
     * 获取一组文件夹的信息
     * @param $uid
     * @param $fid
     * @param $where
     * @return bool
     */
    public function get_folders_info($uid, $fid, $where="", $fields="id,name,pid,path,deleted,access_denied") {
        if (empty($uid) || empty($fid)) return FALSE;

        return $this->share_model->get_folders_info($uid, $fid, $where, $fields);
    }

    /**
     * 判断分享链接是否已经存在数据库
     * @param $list_md5 列表的md5
     * @return array
     */
    public function check_share_code($list_md5) {
        if (empty($list_md5))
            return $this->set_error(1003);

        $list_hash = Common::time33($list_md5);
        $where = array(
            'list_md5_hash' => $list_hash,
            'list_md5' => $list_md5,
        );
        return $this->share_model->check_code_exists($where);
    }

    /**
     * 批量更新下载的标志
     * @param $uid
     * @param $fids 一组文件列表
     * @param int $switch 值 0/1
     * @return null
     */
    public function update_downloaded_batch($uid, $fids) {
        if (empty($uid) || empty($fids))
            return $this->set_error(1003);

        if (! is_array($fids))
            return $this->set_error(1003);

        $data = array();
        foreach($fids as $k=>$v) {
            if (empty($v['file_id'])) {
                if (empty($v['id'])) continue;

                $file_id = $v['id'];
            } else {
                $file_id = $v['file_id'];
            }
            $data[] = $file_id;
        }

        if (empty($data))
            return;

        return $this->share_model->update_downloaded_batch($uid, $data);
    }

    /**
     * @param $uid 用户id
     * @param $files 文件id组
     * @param $folders 文件夹id组
     * @param $name 分享列表名
     * @return array|bool
     */
    public function create_share($uid, $files=array(), $folders=array(), $name='') {
        if (empty($uid) ||
            (empty($files) && empty($folders))) {
            return $this->set_error(1003);
        }

        #分享文件列表名
        $name = ('' === $name) ? $this->lang->line('share_name') : $name;

        $list_str = $this->create_file_str($files, $folders);
        $list_md5 = md5($list_str);  //添加,连接符

        $res = $this->check_share_code($list_md5);
        $list_hash = Common::time33($list_md5);

        //已存在数据
        if (! empty($res))
            return $res;

        //生成分享码
        $share_codes = $this->short_code($list_str.time(), FALSE);
        $share_code = $share_codes[0];
        $share = array(
            "name" => $name, //$list_name
            "share_code" => $share_code,
            'share_code_hash' => Common::time33($share_code),
            'list_md5' => $list_md5,
            'list_md5_hash' => $list_hash,
            'password' => '',
            'uid' => $uid,
            "creation_ts" => time()
        );

        //添加分享
        $flag = $this->doadd($share, $files, $folders);

        if (empty($flag))
            return $this->common_response(1017);

        if (! empty($files))
            $this->share_service->update_shared_batch($uid, $files);
        if (! empty($folders))
            $this->share_service->update_files_shared($uid, $folders);

        $result = array(
            'id' => "$this->last_share_id",
            'share_code' => $share_code,
            'password' => ''
        );

        return $result;
    }

    /**
     * 检测档案是否有分享权限
     * 过滤非本人拥有的文件
     * @param $uid
     * @param string $files 文件列表
     * @param string $folders 文件夹列表
     * @return bool|void
     */
    public function check_file($uid, $files='', $folders='') {
        #可分享标识开关
        $flag = false;
        $res = array(
            'files' => array(),
            'folders' => array(),
        );

        if (! empty($files)) {
            $file_res = $this->get_file_list($uid, $files);
            if (! empty($file_res)) {
                $flag = true;
                $res['files'] = array_column($file_res, "id");
            }
        }

        //文件夹
        if (empty($folders)) {
            if (! empty($res['files']))
                return $res;

            return $this->set_error(7001);
        }

        //取文件夹下的文件
        $folder_files = $this->share_service->get_folder_files($uid, $folders);
        #拥有的的
        $owner_folder = array_column($folder_files['folders'], "id");
        if (! empty($owner_folder))
            $res['folders'] = $owner_folder;

        if ($flag)
            return $res;

        //无文件 , 全部的文件夹均不可分享
        if ( empty($folder_files['files']) ||
            ! isset($folder_files['fds']['pass'])) {
            return $this->set_error(7103);
        }

        //定义未通过
        $unpass_fds = isset($folder_files['fds']['unpass']) ?
            $folder_files['fds']['unpass'] :
            array();

        //判断文件权限
        foreach ($folder_files['files'] as $keys => $l_file) {
            if (($l_file['access_denied'] != 1) &&
                ($l_file['deleted'] != 1)) {

                if (empty($unpass_fds))
                    return $res;

                //该文件父级不受限则
                if (! in_array($l_file['folder_id'], $unpass_fds)) {
                    return $res;
                }
            }
        }
        return $this->set_error(7103);
    }

    /**
     * 更新 分享 的标记
     * @param $uid
     * @param $fids 文件列表
     * @param int $switch 0/1 已分享的开关
     * @return null
     */
    public function update_shared_batch($uid, $fids, $switch=1) {
        if (empty($uid) || empty($fids) || !is_numeric($switch)) return $this->set_error(1003);

        return $this->share_model->update_shared_batch($uid, $fids, $switch);
    }

    /**
     * 更新文件夹的分享标记
     * @param $uid
     * @param $fids 文件夹列表
     * @param int $switch
     */
    public function update_files_shared($uid, $fids, $switch=1) {

       return $this->share_model->update_files_shared($uid, $fids, $switch);
    }

    /**
     * 更新单条分享的信息
     * @param $data 更新的值
     * @param $where 更新的条件
     * @return bool
     */
    public function update_share($where, $value) {
        if (!is_array($where) || !is_array($value)) return NULL;
        if (empty($where) || empty($value)) return NULL;

        return $this->share_model->update_share($where, $value);
    }

    public function update_receivers() {
        return;
    }

    /**
     * 将数据转码并返回一组随机的8位数
     * @param $input 值
     * @param bool $md5type 参数1是否已是md5值
     * @return array
     */
    public function short_code($input, $md5type = TRUE) {
        $base32 = array (
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
            'i', 'j', 'k', 'm', 'n', 'p','q', 'r',
            's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
            'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q',
            'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2',
            '3', '4', '5', '6', '7', '8', '9'
        );

        if ($md5type) {
            $hex = $input;
        } else {
            $hex = md5($input);
        }

        $hexLen = strlen($hex);
        $subHexLen = $hexLen / 8;
        $output = array();

        for ($i = 0; $i < $subHexLen; $i++) {
            $subHex = substr ($hex, $i * 8, 8);
            //php7不可使用
            //$int = 0x3FFFFFFF & (1 * ('0x'.$subHex));
            //php7及以下均可正常使用
            $int = 0x3FFFFFFF & (1 * (filter_var('0x'.$subHex, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX)));
            $out = '';

            for ($j = 0; $j < 8; $j++) {
                $val = 0x0000001F & $int;
                $out .= $base32[$val];
                $int = $int >> 3;
            }

            $output[] = $out;
        }

        return $output;
    }

    /**
     * 分享码算法
     */
    public function create_file_str($files=array(), $folders=array(), $pre="||") {
        if (empty($files) && empty($folders)) return;

        if (! empty($files)) {
            sort($files);
            $res = implode(',', $files);
        }
        if (! empty($folders)) {
            sort($folders);

            if (empty($res)) {
                $res = $pre.implode(',', $folders);
            } else {
                $res .= $pre.implode(',', $folders);
            }
        }
        return $res;
    }

    /**
     * 获取文件 通过分享码id
     * @param $lid 分享码id
     * @return bool
     */
    public function get_files_lid($lid) {
        if (empty($lid)) {
            return $this->set_error(1003);
        }

        return $this->share_model->get_files_lid($lid);
    }

    /**
     * 删除文件 通过分享码id
     * @param $lid 分享码id
     * @return bool
     */
    public function delete_files_lid($lid) {
        if (empty($lid)) {
            return $this->set_error(1003);
        }

        return $this->share_model->delete_files_lid($lid);
    }
}
 
/* End of file share_service.php */
/* Location: ./application/service/share_service.php */